package gateway

import (
	"fmt"
	"github.com/xtaci/smux"
	"net"
	"sync"
	"tinp/mylog"
)

// Session 服务端与客户端的会话
type Session struct {
	ClientId   string
	Connection *smux.Session
}
type SessionManager struct {
	sessionMap map[string]*Session
	sessionMu  sync.RWMutex
}

func NewSessionManager() *SessionManager {
	return &SessionManager{
		sessionMap: make(map[string]*Session),
	}
}
func (mgr *SessionManager) GetSessionByClientId(clientId string) net.Conn {
	mgr.sessionMu.RLock()
	defer mgr.sessionMu.RUnlock()
	session := mgr.sessionMap[clientId]
	if session == nil {
		mylog.Logger.Warnf("get session for client %s fail", clientId)
		return nil
	}
	stream, err := session.Connection.OpenStream()
	if err != nil {
		mylog.Logger.Warnf("open stream fail： %v", err)
		return nil
	}
	return stream
}
func (mgr *SessionManager) CreateSession(clientId string, conn net.Conn) (*Session, error) {
	mgr.sessionMu.Lock()
	defer mgr.sessionMu.Unlock()
	if _, ok := mgr.sessionMap[clientId]; ok {
		return nil, fmt.Errorf("client %s is online", clientId)
	}
	snuxSession, err := smux.Server(conn, nil)
	if err != nil {
		return nil, fmt.Errorf("init smux session fail: %v", err)
	}
	session := &Session{
		ClientId:   clientId,
		Connection: snuxSession,
	}
	mgr.sessionMap[clientId] = session
	return session, nil
}
func (mgr *SessionManager) CloseSession(clientId string) {
	mgr.sessionMu.Lock()
	defer mgr.sessionMu.Unlock()
	session := mgr.sessionMap[clientId]
	if session != nil {
		session.Connection.Close()
		delete(mgr.sessionMap, clientId)
	}
}
func (mgr *SessionManager) Range(c func(k string, v *Session)) {
	mgr.sessionMu.Lock()
	defer mgr.sessionMu.Unlock()
	for clientId, session := range mgr.sessionMap {
		c(clientId, session)
	}
}

func (mgr *SessionManager) DeleteClosedConn() {
	mgr.sessionMu.Lock()
	defer mgr.sessionMu.Unlock()
	for clientId, session := range mgr.sessionMap {
		if session.Connection.IsClosed() {
			mylog.Logger.Warnf("与客户端[%s]会话已断开", clientId)
			delete(mgr.sessionMap, clientId)
			continue
		}
	}
}
